package ajax;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import db.mysql.mySqlUtils;

public class AjaxDelegator extends HttpServlet{

	public void doGet( HttpServletRequest request, HttpServletResponse response )
	throws ServletException, IOException
	{
		doPost(request,response);
	}

	/**
	 *  ex:
	 *  http:// ..... /SW_BOM/Ajax.template?class=com.acer.hb.system.CmCodeDAO&method=findGroupsByCdGroupId&para=SW0018,rmk1
	 *  
	 *  class=class path                 ex:com.acer.hb.system.CmCodeDAO
	 *  method=method name               ex:findGroupsByCdGroupId
	 *  para=parameters                  ex:SW0018,rmk1
	 *  
	 */
	public void doPost( HttpServletRequest request, HttpServletResponse response )
	throws ServletException, IOException
	{
		String action = request.getParameter("action");
		String className = request.getParameter("class");
		String methodName = request.getParameter("method");
		String paras = request.getParameter("para");
		String constructorType = request.getParameter("constructor");
		
		System.out.println("action:" + action);
		if("edit".equals(action)){
			System.out.println("==start AjaxDelegator==1");
			System.out.println("oper:"+request.getParameter("oper"));
			System.out.println("id:"+request.getParameter("id"));
			System.out.println("db_id:"+request.getParameter("db_id"));
			System.out.println("map:"+request.getParameterMap());
			
			try {
				mySqlUtils.commonDbAction(request);
				HashMap temp = new HashMap();
				temp.put("message", "OK");
				net.sf.json.JSON ja = net.sf.json.JSONObject.fromObject(temp); 
				PrintWriter out = response.getWriter();
				out.print(ja);
				out.flush();
			} catch (SQLException e) {
				HashMap temp = new HashMap();
				temp.put("message", "FAIL");
				temp.put("exception", e.getLocalizedMessage());
				
				net.sf.json.JSON ja = net.sf.json.JSONObject.fromObject(temp); 
				PrintWriter out = response.getWriter();
				out.print(ja);
				out.flush();
				e.printStackTrace();
			}
			return;
		}
		
		System.out.println("==start AjaxDelegator==2");
		try{
			// Set to expire far in the past.
			response.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT");
			// Set standard HTTP/1.1 no-cache headers.
			response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
			// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
			response.addHeader("Cache-Control", "post-check=0, pre-check=0");
			// Set standard HTTP/1.0 no-cache header.
			response.setHeader("Pragma", "no-cache");
			response.setCharacterEncoding("utf-8");
			
//			if(className.toLowerCase().indexOf("dao") == -1 && 
//			   className.toLowerCase().indexOf("service") == -1) return;
//			if(methodName.toLowerCase().indexOf("find") == -1 && 
//			   methodName.toLowerCase().indexOf("get") == -1 ) return;
			
			//set parameters
			String paramters[] = null;
			if(paras != null){
				paramters = paras.split(",");
				for(int i = 0; i < paramters.length ; i++){
					if(paramters[i] != null && paramters[i].equals("null")){
						paramters[i] = null;
					}
				}
			}
			
//			DataSource ds = DataSourceHelper.getInstance(InitialConstants._AUTH_JNDI_NAME);
			
			Class xClass = Class.forName(className);  // get class by string
			
			Object obj = null;
			if("HttpServletRequest".equals(constructorType)){
				Class[] types = { HttpServletRequest.class };
				java.lang.reflect.Constructor constructor = xClass.getConstructor(types);
				Object[] params = { request };
				obj = constructor.newInstance( params );
//			}else if("DataSource".equals( constructorType )){
//				Class[] types = new Class[]{ DataSource.class };
//				Constructor constructor = xClass.getConstructor( types );
//				Object[] params = new Object[]{ ds };
//				obj = constructor.newInstance(params); // new object
			}else{
				obj = xClass.newInstance(); // new object
			}
			Method[] ms = xClass.getMethods(); // get methods of object
			System.out.println("ms:" + ms.length);
			for(int i = 0 ; i < ms.length ; i++){ // execute method
				Type type[] = ms[i].getGenericParameterTypes(); // get ParameterType
				if(
				   ms[i].getName().equals(methodName) && 
				   ((type == null && paramters == null) || (type != null && paramters != null && type.length == paramters.length ))
				   )
				{
					Class returnType = ms[i].getReturnType();
					System.out.println("returnType:" + returnType);
					if(returnType == String.class){
						String temp = (String)ms[i].invoke(obj,paramters);
						//20100702
						if(temp!=null){
							List list = new ArrayList();
							list.add(temp);
							net.sf.json.JSONArray ja = net.sf.json.JSONArray.fromObject(list); 
							PrintWriter out = response.getWriter();
							out.print(ja);
							out.flush();
						}
						//class java.util.HashMap
					} else if ("class java.util.HashMap".equals(returnType.toString())){ // String array
						HashMap temp = (HashMap)ms[i].invoke(obj,paramters);
						net.sf.json.JSON ja = net.sf.json.JSONObject.fromObject(temp); 
						PrintWriter out = response.getWriter();
						out.print(ja);
						out.flush();
					} else if ("class [Ljava.lang.String;".equals(returnType.toString())){ // String array
						String[] temp = (String[])ms[i].invoke(obj,paramters);
						net.sf.json.JSONArray ja = net.sf.json.JSONArray.fromObject(temp); 
						PrintWriter out = response.getWriter();
						out.print(ja);
						out.flush();
					} else if(returnType == List.class || returnType == ArrayList.class ){
						List temp = (List)ms[i].invoke(obj,paramters);
						//change hibernate object to map
						if(temp != null && !temp.isEmpty() && temp.size() > 0){
							for(int j = 0 ; (temp.get(0).getClass().toString().indexOf(".hb.") != -1)
							&& j < ms.length ; j++){
								if(
										ms[j].getName().equals("objectList2MapList") 
										&& temp != null && temp.size() > 0 
										&& temp.get(0).getClass().toString().indexOf("java") == -1
								)
								{
									Object arg[] = {temp};
									temp = (List)ms[j].invoke(obj, arg); // execute method
								}
							}
						}
						
						net.sf.json.JSONArray ja = net.sf.json.JSONArray.fromObject(temp); 
						PrintWriter out = response.getWriter();
						out.print(ja);
						out.flush();
					} else {
						Object x = ms[i].invoke(obj,paramters);
						HashMap temp = null;
						if (x.getClass().toString().toLowerCase().indexOf(".hb.") != -1){
							for(int j = 0 ; j < ms.length ; j++){
								if(
									ms[j].getName().equals("object2Map")
								)
								{
									Object arg[] = {x};
									temp = (HashMap)ms[j].invoke(obj, arg); // execute method
								}
							}
						}
						
						net.sf.json.JSONObject ja = net.sf.json.JSONObject.fromObject(temp); 
						PrintWriter out = response.getWriter();
						out.print(ja);
						out.flush();
					}
				}
			}
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public AjaxDelegator(){
	}

	/**
	 * 測試函數
	 *  */
	public static void main(String[] args) {
		try{
			String className = "com.acer.hb.system.CmCodeDAO";
			Class xClass = Class.forName(className);  // get class by string 
			Object o = xClass.newInstance(); // new object
			Method[] ms = xClass.getMethods(); // get methods of object
			List temp = null;
			for(int i = 0 ; i < ms.length ; i++){
				if(ms[i].getName().equals("findByCdGroupId")){
					String arg[] = {"SW0004"};
					temp = (List)ms[i].invoke(o, arg); // execute method
				}
			}
			for(int i = 0 ; i < ms.length ; i++){
				if(ms[i].getName().equals("objectList2MapList")){
					Object arg[] = {temp};
					temp = (List)ms[i].invoke(o, arg); // execute method
				}
			}
			net.sf.json.JSONArray ja = net.sf.json.JSONArray.fromObject(temp);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}	
}